package com.hsyg.netty.server.handler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 *
 */
@SuppressWarnings("all")
public class ServerHandler extends
  // ChannelHandlerAdapter {
  ChannelInboundHandlerAdapter {

  @Override
  public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
    super.channelRegistered(ctx);
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    //将msg转成netty的ByteBuf对象
    ByteBuf buf = (ByteBuf) msg;
    //
    byte[] bytes = new byte[
      //通过readableBytes方法获取缓冲区可读的字节数，根据可读的字节创建byte数组
      buf.readableBytes()
      ];

    //将缓冲区中的字节数组复制到新建的byte数组中
    buf.readBytes(bytes);
    //最后通过new String 构造函数获取请求消息
    String message = new String(bytes, "UTF-8");
    System.out.println("服务端收到的消息： " + message);

    //向客户端写数据
    String response = "hello client";
    ByteBuf buffer = Unpooled.copiedBuffer(response.getBytes());
    //通过write的异步发送应答消息给客户端
    ctx.write(buffer);//写入缓冲数组
  }

  /**
   * 将消息发送队列中的消息写入到SocketChannel中发送给对象
   * 从性能的考虑，为了防止频繁的唤醒Selector进行消息发送，netty的write方法并不直接将消息
   * 写入SocketShannel中，调用write方法只是把待发送的消息放到发送缓冲数组中，再通过调用flush方法，
   * 将发送缓冲区中的消息全部写入到SocketChannel中。
   *
   * @param ctx
   * @throws Exception
   */
  @Override
  public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    System.out.println("channelReadComplete...");
    ctx.flush();//将缓冲区数据写入SocketChannel
  }

  /**
   * 当发生异常时， 关闭ChannelHandlerContext，释放ChannelHandlerContext相关联的句柄等资源
   *
   * @param ctx
   * @param cause
   * @throws Exception
   */
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    System.out.println("exceptionCaught...");
    ctx.close();
  }
}
